package com.woniu.gateway.filter;

import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.exception.CustomException;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.token.AccToken;
import com.ruoyi.common.utils.token.JwtTokenUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

@Component
public class AuthFilter implements GlobalFilter, Ordered {

    @Autowired
    private StringRedisTemplate redisTemplate;

    //不需要验证直接放行的url列表
    private List<String> passUrlList = new ArrayList<>();

    //普通用户请求url列表
    private List<String> webUrlList = new ArrayList<>();

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {

        // 不需要验证直接放行的url
        passUrlList.add("/api/system/captchaImage");
        passUrlList.add("/api/auth/login");
        passUrlList.add("/api/auth/web/login");
        passUrlList.add("/api/user/tbcustomer/queryWebCode");
        passUrlList.add("/api/user/tbcustomer/webRegister");
            //------------------------------------------------------>少侠
        passUrlList.add("/api/apartment/tbcomments/web/listByApartIdAndUserId");
        passUrlList.add("/api/apartment/tbwish/web/likeById");
        passUrlList.add("/api/apartment/tbapartmentmain/web/queryApartmentById");
        passUrlList.add("/api/apartment/tbcomments/web/listByApartId");
        webUrlList.add("/api/apartment/tbwish/web/changeWish");
        webUrlList.add("/api/apartment/tbcomments/web/add");
        //------------------------------------------------------>少侠
        passUrlList.add("/api/user/tbcustomer/checkWebUserName");
        passUrlList.add("/api/user/tbcustomer/uploadWebUser");
        //------------------------------------------------------>王舒成
        passUrlList.add("/api/apartment/tbapartmentmain/web/SearchCityOrUniversityOrApartmentNameForList");
        passUrlList.add("/api/apartment/tbapartmentmain/web/searchNearbyPopularCityApartmentList");
        passUrlList.add("/api/apartment/tbpopularcity/web/list");
        passUrlList.add("/api/apartment/tbapartmentmain/web/SearchCityOrUniversityOrApartmentNameForList");





        //需要验证登录的url
        webUrlList.add("/api/auth/web/login");
        webUrlList.add("/api/coupon/coupon/tbcoupon/web/getNewCoupon");
        webUrlList.add("/api/user/tbcustomer/initWebUserInfo");


        webUrlList.add("/api/user/tbcustomer/initWebUserInfo");
        webUrlList.add("/api/book/pk");
        webUrlList.add("/api/book/makeBook");
        webUrlList.add("/api/coupon/tbcoupon/web/getCouponByApartmentIdAndCustomerId");
        webUrlList.add("/api/apartment/tbnationality/list");
        webUrlList.add("/api/apartment/tbroom/orderRoom");
        webUrlList.add("/api/finance/tbapartfee/web/editPid");
        webUrlList.add("/api/book/getBook");



        //------------------------------------------------------>少侠
        webUrlList.add("/api/apartment/tbcomments/web/listByApartIdAndUserId");
        webUrlList.add("/api/apartment/tbwish/web/likeById");
        webUrlList.add("/api/apartment/tbapartmentmain/web/queryApartmentById");
        webUrlList.add("/api/apartment/tbcomments/web/listByApartId");
        webUrlList.add("/api/apartment/tbwish/web/changeWish");
        webUrlList.add("/api/apartment/tbcomments/web/add/");
        webUrlList.add("/api/apartment/tbwish/web/changeWish");
        webUrlList.add("/api/apartment/tbwish/web/changeWish");
        webUrlList.add("/api/apartment/tbcomments/web/add/");
        webUrlList.add("/api/book/getBookByIds");
        webUrlList.add("/api/book/remove");

        //------------------------------------------------------>少侠

        //获取用户请求的uri
        String uri = exchange.getRequest().getPath().toString();

        //如果uri在放行列表中，直接放行
        if (passUrlList.contains(uri)){
            System.out.println(uri);
            return chain.filter(exchange);
        }

        // 如果不在放行列表中就要判断是否登录,获取用户token
        // 前端页面js中设置了 Authorization ---> 'Bearer ' + getToken() 让每个请求携带自定义token 请根据实际情况自行修改
        //1.从请求头中获取JWT
        String authorization = exchange.getRequest().getHeaders().getFirst("Authorization");
        System.out.println("token ---> "+authorization);

        // 重构方法,验证token转对象
        AccToken accToken = checkJwt(authorization, uri);

        if (accToken == null){
            exchange.getResponse().setRawStatusCode(401);
            return exchange.getResponse().setComplete();
        }

        //把token中的userId取出，放入到request Header
        ServerHttpRequest newRequest = exchange.getRequest().mutate()
                .header("userAccount", "" + accToken.getUserAccount())
                .header("userName", "" + accToken.getUserName())
                .header("Authorization", "" + accToken.getUserAccount())
                .header("userId", "" + accToken.getUserId()).build();

        return chain.filter(exchange.mutate().request(newRequest).build());

    }

    //----------------------------------------------------------------------------------------
    //检查jwt的有效性（重构）
    private AccToken checkJwt(String authorization,String uri){

        // 获取不到token,用户没登录
        if (authorization == null){
            return null;
        }

        // 截取掉'Bearer ' , 得到token
        String jwt = authorization.substring(7);

        // 检查jwt是否过期
        // 每次请求从redis中获取设置时间的token
        String jwtInRedis = (String) redisTemplate.opsForValue().get(jwt);
        System.out.println("jwtInRedis : "+jwtInRedis);
        if (jwtInRedis != null){

            // 每次请求都重新设置过期时间
            redisTemplate.opsForValue().set(jwt,jwt,30, TimeUnit.MINUTES);
        }else {

            // token过期,重新登录
            return null;
        }

        //验证token的有效性
        if(webUrlList.contains(uri)){

            // web 端的token,用web还原
            return JwtTokenUtils.parseWebToken(jwt);
        }


        // 后端管理的token解析
        return JwtTokenUtils.parseToken(jwt);

    }

    @Override
    public int getOrder() {
        return 0;
    }
}
